#pragma once

#include <GL/gl.h>
#include <cstdio>
#include "../gl/Drawabe.h"

struct __attribute__((__packed__))  TriangleInfo {
    Vector3f normal;
    Vector3f vertex[3];
    uint16_t attrs;
};

class View {
private:
    const float cube_size = 1.0f;
    RotateValue view_rotation = {.angle=30, .vector = {.x = 0.1, .y = 0.1, .z = 0.2}};
    RotateValue view_rotation_inc  = {.angle=1, .vector = {.x = 0.2, .y = 0.3, .z = 0.02}};
    Vector3f translate = {.x = 0,.y = 0, .z = -35};
    float dt_x = 0;
    float dt_y = 0;

    GLint list;

public:

    explicit View() {
    }

    void move(int x, int y) {
        printf("x:%d, y:%d\n", x, y);
        dt_x = float(x)/20;
        dt_y = -float(y)/20;
    }

    void commit_move() {
        translate.x+=dt_x;
        translate.y+=dt_y;
        dt_x = 0;
        dt_y = 0;
        printf("commit\n");
    }

    void init() {
        list = glGenLists(1);
        glNewList(list, GL_COMPILE);
        //FILE * stl_file = fopen("res/hedgehog.stl", "r");
        FILE * stl_file = fopen("res/tyrunt_stl.stl", "r");

        if (stl_file) {

            Point3f * rgb = new Point3f(1, 0.6, 0);
            glBegin(GL_TRIANGLES);                // Begin drawing the color cube with 6 quads
            fseek(stl_file, 80, SEEK_SET);
            int nubber_of_triangles;
            fread(&nubber_of_triangles, 4, 1, stl_file);
            //printf("%d\n", nubber_of_triangles);
            TriangleInfo ti;
            for (int i=0;i<nubber_of_triangles;i++) {
                int readed = fread(&ti, sizeof(TriangleInfo), 1, stl_file);
                if (readed==0)
                    printf("No data\n");
                else {
                    if (ti.attrs)
                        printf("Attrs %d\n", ti.attrs);
                    glNormal3f(ti.normal.x, ti.normal.y, ti.normal.z);
                    glVertex3f( ti.vertex[0].x, ti.vertex[0].y, ti.vertex[0].z);
                    glVertex3f( ti.vertex[1].x, ti.vertex[1].y, ti.vertex[1].z);
                    glVertex3f( ti.vertex[2].x, ti.vertex[2].y, ti.vertex[2].z);
                }
            }
            fclose(stl_file);
            glEnd();
            //printf("end\n");
        }
        glEndList();
    }

    void inc_rotation() {
        this->view_rotation+=this->view_rotation_inc;
    }

    void inc_translate(bool forward) {
        if (forward) {
            this->translate.z -= 1;
        } else
            this->translate.z += 1;
    }


    void draw() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers
        float bluish[4] = { 1, 1, 1, 1 };
        glLightfv(GL_LIGHT1, GL_DIFFUSE, bluish);
        glLightfv(GL_LIGHT1, GL_SPECULAR, bluish);
        glEnable(GL_LIGHT1);


        glMatrixMode(GL_MODELVIEW);     // To operate on model-view matrix
        glDepthFunc(GL_LESS);
        glLoadIdentity();                 // Reset the model-view matrix
        glPushMatrix();
        glTranslatef(translate.x + dt_x, translate.y + dt_y, translate.z);  // Move right and into the screen
        glRotatef(view_rotation.angle, view_rotation.vector.x, view_rotation.vector.y, view_rotation.vector.z);
        glPushMatrix();
        glScalef(0.1, 0.1, 0.1);

        GLfloat spec[4] = { 0.5, 0.5, 0.5, 1 };
        GLfloat diff[4] = { 0.75, 0, 0, 1 };
        glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
        glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, diff);
        glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 5);

        glCallList(list);
        glPopMatrix();
        glPopMatrix();
        glutSwapBuffers();  // Swap the front and back frame buffers (double buffering)
    }
};